from khronos.utils import Call

class Formatter(object):
    def __init__(self, format="%s", indent=""):
        self.format = format
        self.indent = indent
        self.lines = []
        
    def __str__(self):
        return "\n".join(self.lines)
        
    def set_format(self, format):
        self.format = format
        
    def set_indent(self, indent):
        self.indent = indent
        
    def add_plain(self, line, indent=True):
        if indent:
            line = self.indent + line
        self.lines.append(line)
        
    def add_formatted(self, data, indent=True):
        line = self.format % data
        if indent:
            line = self.indent + line
        self.lines.append(line)
        
class FormatterCommand(object):
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        
class fmt(object):
    class set_format(FormatterCommand):
        handler = Formatter.set_format
        
    class set_indent(FormatterCommand):
        handler = Formatter.set_indent
        
    class add_plain(FormatterCommand):
        handler = Formatter.add_plain
        
    class add_formatted(FormatterCommand):
        handler = Formatter.add_formatted
        
def formatted(fnc=None, format="%s", indent=""):
    if fnc is None:
        return Call(formatted, format=format, indent=indent)
    def new_fnc(*args, **kwargs):
        fmt = Formatter(format=format, indent=indent)
        for command in fnc(*args, **kwargs):
            if isinstance(command, FormatterCommand):
                command.handler(fmt, *command.args, **command.kwargs)
            else:
                fmt.add_formatted(command)
        return str(fmt)
    new_fnc.__name__ = fnc.__name__
    new_fnc.__doc__ = fnc.__doc__
    return new_fnc
    
"""
@formatted
def report():
    yield fmt.set_format("%d + 1 = %d")
    for x in xrange(3):
        yield x, x+1
    yield fmt.set_indent("    ")
    yield fmt.add_plain("____")
    for x in xrange(3):
        yield x, x+1
    yield fmt.add_plain("____")
"""
